package com.future.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.JsonNode;
import com.future.dto.BaiDuAIRequestInfoDto;
import com.future.dto.ImgBasePathDto;
import com.future.mapper.*;
import com.future.po.*;
import com.future.service.*;
import com.future.utils.BeanUtils;
import com.future.utils.DateUtil;
import com.future.utils.JacksonUtil;
import com.future.vo.IllegalImgVo;
import com.future.vo.QueryInfoVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class MonitorOfDrivingServiceImpl implements MonitorOfDrivingService {

    @Autowired
    private YSOpenService ysOpenService;

    @Autowired
    private BaiDuAIService baiDuAIService;

    @Autowired
    private DrivingStatisService drivingStatisService;

    @Autowired
    @SuppressWarnings("all")
    private DrivingUserStandardMapper drivingUserStandardMapper;

    @Autowired
    @SuppressWarnings("all")
    private DrivingStandardMapper drivingStandardMapper;

    @Autowired
    @SuppressWarnings("all")
    private DrivingImgMapper drivingImgMapper;

    @Autowired
    @SuppressWarnings("all")
    private DrivingDriverMapper drivingDriverMapper;

    @Autowired
    private BaiDuAIRequestInfoDto baiDuAIRequestInfoDto;

    @Autowired
    private ImgBasePathDto imageBasePathDto;

    @Override
    public String monitor(User user) throws Exception {
        // 通过萤石的接口进行截图，并拿到截图数据。参数是对图片的路径进行设置
        File monitorImg = ysOpenService.capture(imageBasePathDto.getDrivingMonitorPath() + "/" + user.getUsername());
        // 应用AI对图片进行检测，拿到字符串返回值
        String result = baiDuAIService.check(monitorImg, baiDuAIRequestInfoDto.getURLOfDrivingBehavior());
        // 转换格式到对象
        JsonNode personInfo = JacksonUtil.jsonNodeOf(result, "person_info");
        System.out.println(personInfo.toString());
        System.out.println("__________________________");
        // mybatisplus，查询一条数据的条件语句。Java类id与数据库user_id字段绑定，两相等的，查一条，
        // 根据当前用户的id，
        DrivingUserStandard userStandard = drivingUserStandardMapper.selectOne(new QueryWrapper<DrivingUserStandard>().eq("user_id", user.getId()));


        boolean flag = true; // 用于标识图片是否出现了非法信息， true表示未出现，false表示出现
        LinkedList<DrivingDriver> list = new LinkedList<>();
        DrivingDriver driver = new DrivingDriver();

        // 大意就是解析Json报文，并封装
        for (int i = 0; i < personInfo.size(); i++) {
            // 获取personInfo的attributes属性值
            JsonNode attributes = JacksonUtil.jsonNodeOf(personInfo.get(i), "attributes");

            // 人体框的信息
            Integer locHeight = JacksonUtil.jsonNodeOf(personInfo.get(i), "location", "height").asInt();
            Integer locWidth = JacksonUtil.jsonNodeOf(personInfo.get(i), "location", "width").asInt();
            Integer locLeft = JacksonUtil.jsonNodeOf(personInfo.get(i), "location", "left").asInt();
            Integer locTop = JacksonUtil.jsonNodeOf(personInfo.get(i), "location", "top").asInt();
            driver.setLocHeight(locHeight);
            driver.setLocWidth(locWidth);
            driver.setLocLeft(locLeft);
            driver.setLocTop(locTop);
            // 吸烟
            double smoke = JacksonUtil.jsonNodeOf(attributes, "smoke", "threshold").asDouble();
            double smokeScore = JacksonUtil.jsonNodeOf(attributes, "smoke", "score").asDouble();
            if (smokeScore > smoke) {
                driver.setSmoke(1);
                flag = false;
            } else {
                driver.setSmoke(0);
            }
            // 打手机
            double cellphone = JacksonUtil.jsonNodeOf(attributes, "cellphone", "threshold").asDouble();
            double cellphoneScore = JacksonUtil.jsonNodeOf(attributes, "cellphone", "score").asDouble();
            if (cellphoneScore > cellphone) {
                System.out.println("打电话了");
                driver.setCellphone(1);
                flag = false;
            } else {
                driver.setCellphone(0);
            }
            // 未系安全带
            double notBucklingUp = JacksonUtil.jsonNodeOf(attributes, "not_buckling_up", "threshold").asDouble();
            double notBucklingUpScore = JacksonUtil.jsonNodeOf(attributes, "not_buckling_up", "score").asDouble();
            if (notBucklingUpScore > notBucklingUp) {
                System.out.println("没系安全带");
                driver.setNotBucklingUp(1);
                flag = false;
            } else {
                System.out.println("已系安全带");
                driver.setNotBucklingUp(0);
            }
            // 双手离开方向盘
            double bothHandsLeavingWheel = JacksonUtil.jsonNodeOf(attributes, "both_hands_leaving_wheel", "threshold").asDouble();
            double bothHandsLeavingWheelScore = JacksonUtil.jsonNodeOf(attributes, "both_hands_leaving_wheel", "score").asDouble();
            if (bothHandsLeavingWheelScore > bothHandsLeavingWheel) {
                driver.setBothHandsLeavingWheel(1);
                System.out.println("手离开方向盘");
                flag = false;
            } else {
                System.out.println("手握住方向盘");
                driver.setBothHandsLeavingWheel(0);
            }
            // 视角未朝前方
            double notFacingFront = JacksonUtil.jsonNodeOf(attributes, "not_facing_front", "threshold").asDouble();
            double notFacingFrontScore = JacksonUtil.jsonNodeOf(attributes, "not_facing_front", "score").asDouble();
            if (notFacingFrontScore > notFacingFront) {
                System.out.println("眼睛没看前方");
                driver.setNotFacingFront(1);
                flag = false;
            } else {
                System.out.println("眼睛在看前方");
                driver.setNotFacingFront(0);
            }
            // 未正确佩戴口罩
            double noFaceMask = JacksonUtil.jsonNodeOf(attributes, "no_face_mask", "threshold").asDouble();
            double noFaceMaskScore = JacksonUtil.jsonNodeOf(attributes, "no_face_mask", "score").asDouble();
            if (noFaceMaskScore > noFaceMask) {
                System.out.println("没戴口罩");
                driver.setNoFaceMask(1);
                flag = false;
            } else {
                System.out.println("戴口罩了");
                driver.setNoFaceMask(0);
            }
            // 打哈欠
            double yawning = JacksonUtil.jsonNodeOf(attributes, "yawning", "threshold").asDouble();
            double yawningScore = JacksonUtil.jsonNodeOf(attributes, "yawning", "score").asDouble();
            if (yawningScore > yawning) {
                System.out.println("在打呵欠");
                flag = false;
                driver.setYawning(1);
            } else {
                System.out.println("没打呵欠");
                driver.setYawning(0);
            }
            // 闭眼
            // 阈值：参考概率上限
            double eyesClosed = JacksonUtil.jsonNodeOf(attributes, "eyes_closed", "threshold").asDouble();
            // 得分：实际概率上限
            double eyesClosedScore = JacksonUtil.jsonNodeOf(attributes, "eyes_closed", "score").asDouble();
            if (eyesClosedScore > eyesClosed) {
                System.out.println("闭眼G了");
                driver.setEyesClosed(1);
                flag = false;
            } else {
                System.out.println("没有闭眼");
                driver.setEyesClosed(0);
            }
            // 低头
            double headLowered = JacksonUtil.jsonNodeOf(attributes, "head_lowered", "threshold").asDouble();
            double headLoweredScore = JacksonUtil.jsonNodeOf(attributes, "head_lowered", "score").asDouble();
            if (headLoweredScore > headLowered) {
                System.out.println("还敢低头");
                flag = false;
                driver.setHeadLowered(1);
            } else {
                System.out.println("没低头");
                driver.setHeadLowered(0);
            }

            // 设置基本信息
            driver.setCreateTime(LocalDateTime.now());
            driver.setUpdateTime(LocalDateTime.now());
            list.add(driver);
        }

        System.out.println("__________________________");
        // 保存非法监控图像

        if (flag) { // 图片未出现非法信息
            System.out.println("图片未出现非法信息");
            monitorImg.delete();
            return null;
        } else {
            System.out.println("图片出现非法信息");

            DrivingImg drivingImg = new DrivingImg();
            drivingImg.setPath(monitorImg.getPath());
            drivingImg.setUserId(user.getId());
            drivingImgMapper.insert(drivingImg);

            // 保存非法监控信息，将所有满足条件的存储，
            for (DrivingDriver drivingDriver : list) {
                drivingDriver.setImgId(drivingImg.getId());
                drivingDriver.setUserId(user.getId());
                drivingDriverMapper.insert(drivingDriver);

                DrivingStatis statis = drivingStatisService.getOne(new QueryWrapper<DrivingStatis>().eq("user_id", user.getId()).eq("date", DateUtil.toDate(drivingDriver.getCreateTime().toString(), "yyyy-MM-dd")));
                if (statis == null) {
                    statis = new DrivingStatis();
                    statis.setDate(DateUtil.toDate(drivingDriver.getCreateTime().toString(), "yyyy-MM-dd"));
                    statis.setUserId(user.getId());
                    drivingStatisService.save(statis);
                } else {
                    statis.setUpdateTime(LocalDateTime.now());
                    statis.setTotalNum(statis.getTotalNum() + 1);
                    statis.setUntreatedNum(statis.getUntreatedNum() + 1);
                    drivingStatisService.updateById(statis);
                }
            }
        }
        return formatData(driver);
    }

    @Override
    public List<IllegalImgVo> findImgsAll(User user,QueryInfoVo queryInfo) {

        if (queryInfo==null){
            queryInfo= new QueryInfoVo();
            queryInfo.setPageNum(1);
            queryInfo.setPageSize(10);
        }
        Integer pageNum = queryInfo.getPageNum();
        Integer pageSize = queryInfo.getPageSize();
        String startDate = queryInfo.getStartDate();
        String endDate = queryInfo.getEndDate();
        Page<DrivingDriver> page = new Page<>(pageNum,pageSize);
        QueryWrapper<DrivingDriver> wrapper = new QueryWrapper<DrivingDriver>();

        if (startDate!=null && !"".equals(startDate)){
            wrapper.ge("create_time",startDate);
        }
        if (endDate!=null && !"".equals(endDate)){
            wrapper.le("create_time",endDate);
        }
        wrapper.eq("user_id", user.getId()).orderByDesc("create_time");
//        List<DrivingDriver> drivingDrivers = drivingDriverMapper.selectList(wrapper);
        IPage<DrivingDriver> drivingDriverPage = drivingDriverMapper.selectPage(page, wrapper);
        List<DrivingDriver> drivingDrivers = drivingDriverPage.getRecords();
        List<IllegalImgVo> drivingImgVoList = new ArrayList<>();
        for (DrivingDriver drivingDriver : drivingDrivers) {
            DrivingImg drivingImg = drivingImgMapper.selectOne(new QueryWrapper<DrivingImg>().eq("id", drivingDriver.getImgId()));

            IllegalImgVo illegalImgVo = new IllegalImgVo();
            BeanUtils.copyBeanProp(illegalImgVo, drivingDriver);
            illegalImgVo.setPath(drivingImg.getPath());
            illegalImgVo.setCreateTime(drivingImg.getCreateTime());
            illegalImgVo.setStatus(drivingImg.getStatus());

            illegalImgVo.setData(drivingDriver);

            drivingImgVoList.add(illegalImgVo);
        }
        return drivingImgVoList;
    }

    /**
     * 将当前截取图片检测后的结果数据进行字符串格式化
     * @param dd
     * @return
     */
    private String formatData(DrivingDriver dd){
        StringBuffer sb = new StringBuffer("{\"createTime\":\"" + dd.getCreateTime() + "\",\"updateTime\":\"" + dd.getUpdateTime() + "\",");

        if (dd.getCellphone() != 0){
            sb.append("\"cellphone\":1,");
        }
        if (dd.getSmoke() != 0){
            sb.append("\"somke\":1,");
        }
        if (dd.getYawning() != 0){
            sb.append("\"yawning\":1,");
        }
        if (dd.getNotFacingFront() != 0){
            sb.append("\"not_facing_front\":1,");
        }
        if (dd.getNotBucklingUp() != 0){
            sb.append("\"not_buckling_up\":1,");
        }
        if (dd.getNoFaceMask() != 0){
            sb.append("\"no_face_mask\":1,");
        }
        if (dd.getHeadLowered() != 0){
            sb.append("\"head_lowered\":1,");
        }
        if (dd.getEyesClosed() != 0){
            sb.append("\"eye_closed\":1,");
        }
        if (sb.lastIndexOf(",") != -1){
            sb.replace(sb.lastIndexOf(","),sb.lastIndexOf(",") + 1, "");
        }
        sb.append("}");
        return sb.toString();
    }
}
